// 把对象转换成 查询字符串
function querystringify(obj) {
  let str = ''

  for (var key in obj) {
    str += key + '=' + obj[key] + '&'
  }

  return str.slice(0, -1)
}

// 把一个对象转换成 查询字符串 格式
// function fn(obj) {
//   // obj 就是你要转换的对象数据类型
//   console.log(obj)
//   let str = ''
//   // 因为查询字符串的格式 key=value&key2=value2
//   // 我们要拿到 obj 内的每一个 键 和 值
//   for (var k in obj) {
//     // k 就是每一个键
//     // obj[k] 就是每一个值
//     str += k + '=' + obj[k] + '&'
//   }

//   return str.slice(0, -1)
// }

// // 将来使用的时候
// const s = fn({ a: 100, b: 200, c: 300 })
// console.log(s)





// ajax 封装
/*
  1. 对你传递的参数进行验证
    1-1. 验证你的 options 内 url 必填
      => 如果你没有 url, 不需要继续执行代码了
    1-2. 验证你的 options 内的 method 填写
      => 可以不传递, 只要你传递了, 必须是 GET 或者 POST
    1-3. 验证你的 options 内的 async 填写
      => 可以不传递, 只要你传递了, 必须是 true 或者 false
    1-4. 验证你的 options 内的 data 填写
      => 可以不传递, 只要你传递了, 必须是 字符串 类型
    1-5. 验证你的 options 内的 token 填写
      => 可以不传递, 只要你传递了, 必须是 字符串 类型
    1-6. 验证你的 options 内的 dataType 填写
      => 可以不传递, 只要你传递了, 必须是 'string' 或者 'json'
    1-7. 验证你的 options 内的 success 填写
      => 可以不传递, 只要你传递了, 必须是一个 function 类型
*/

function ajax(options = {}) {
  // options 就是你传递进来的所有对于本次请求的配置信息
  // console.log('你传递进来的数据 : ', options)

  // 1. 参数验证
  // 1-1. 验证 options.url
  if (!options.url) {
    // 表示 url 是 undefined 或者 null 或者 '' 或者 0
    // 手动抛出异常
    // 语法: throw new Error('报错信息')
    // 作用: 直接在控制台报错, 阻断程序的继续执行
    throw new Error('url 为必填选项, 请填写 ^_^')
  }

  // 1-2. 验证 options.method
  // 可以是 undefined, 可以是 'GET', 可以是 'POST'
  if (!(options.method === undefined || /^(get|post)$/i.test(options.method))) {
    // 代码能执行到这里, 说明你的 method 不是 undefined 不是 get 不是 post
    throw new Error('目前版本只接受 GET 和 POST 请求, 请期待更新 !! (#^.^#)')
  }

  // 1-3. 验证 options.async
  // 可以是 undefined, 可以是 布尔值
  if (!(options.async === undefined || typeof options.async === 'boolean')) {
    throw new Error('async 只能传递 布尔值, 请检查后操作')
  }

  // 1-4. 验证 options.data
  if (!(options.data === undefined || typeof options.data === 'string')) {
    throw new Error('data 需要传递一个 字符串 格式')
  }

  // 1-5. 验证 options.token
  if (!(options.token === undefined || typeof options.token === 'string')) {
    throw new Error('token 需要传递一个 字符串 格式')
  }

  // 1-6. 验证 options.dataType
  if (!(options.dataType === undefined || /^(string|json)$/i.test(options.dataType))) {
    throw new Error('dataType 只能传递 "string" 或者 "json"')
  }

  // 1-7. 验证 options.success
  if (!(options.success === undefined || typeof options.success === 'function')) {
    throw new Error('success 需要传递一个 function 类型的数据')
  }

  // 2. 设置一套默认值
  const _default = {
    // 代码能执行到这里, 说明 url 必须有值
    url: options.url,
    // 代码能来到这里, 说明 method 要么是 undefined, 要么是 GET, 要么是 POST
    method: options.method || 'GET',
    // 代码能来到这里, 说明 async 要么是 undefined, 要么是 true 要么是 false
    async: typeof options.async === 'boolean' ? options.async : true,
    // async: options.async ?? true
    // 代码能来到这里, 说明 data 要么是 undefined, 要么是 字符串
    data: options.data || '',
    // 代码能来到这里, 说明 token 要么是 undefined, 要么是 字符串
    token: options.token || '',
    // 代码能来到这里, 说明 dataType 要么是 undefined, 要么是 string 或者 json
    dataType: options.dataType || 'string',
    // 代码能来到这里, 说明 success 要么是 undefined, 要么是一个 函数
    success: options.success || function () {},
    error: options.error || function () {}
  }
  // 2-2. 判断一下, 如果是 GET 请求, 并且 data 有内容
  // 那么我们直接把 data 拼接到 url 的后面
  if (_default.method.toUpperCase() === 'GET' && _default.data) {
    // 代码能来到这里, 说明 是 GET 请求, 并且 data 有内容
    _default.url += '?' + _default.data
  }

  // 3. 按照 _default 内的内容发送请求

  // 3-1. 创建 ajax 对象
  const xhr = new XMLHttpRequest()

  // 3-2. 配置请求信息
  xhr.open(_default.method, _default.url, _default.async)

  // 3-3. 接受响应
  xhr.onload = function () {
    // 判断一下, 如果 dataType 是 'string' 那么我就不执行 JSON.parse()
    // 如果你的 dataType 是 'json' 那么我就执行一下 JSON.parse()
    const result = _default.dataType.toUpperCase() === 'JSON' ? JSON.parse(xhr.responseText) : xhr.responseText

    // 请求完成, 只要调用 success 函数就可以了
    _default.success(result)
  }

  // 3-4. 是否填写 token 作为请求头内的一个信息
  if (_default.token) xhr.setRequestHeader('authorization', _default.token)

  // 3-5. 如果是 POST 请求, 设置一下请求头的格式
  if (_default.method.toUpperCase() === 'POST') xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')

  // 3-6. 发送请求
  // 如果是 GET 请求, 直接书写 xhr.send()
  // 如果是 POST 请求你, 书写 xhr.send(参数)
  _default.method.toUpperCase() === 'POST' ? xhr.send(_default.data) : xhr.send()
}


// 对 ajax 进行 二次封装
function pAjax(options = {}) {
  const p = new Promise((resolve, reject) => {
    // 执行 ajax
    ajax({
      url: options.url,
      data: options.data,
      token: options.token,
      async: options.async,
      method: options.method,
      dataType: options.dataType,
      success: function (res) {
        resolve(res)
      }
    })
  })

  // 把我的 promise 对象返回出去
  return p
}

// 此时的全局变量 a 和 pAjax 内的 局部变量 p 是一模一样的东西
// const a = pAjax({ url: '/xxx', data: 'xxx', dataType: 'xxxx' })
// a.then(res => {})
